package com.internetCafes.spms.web.customer.bizservice.impl.area;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.internetCafes.spms.common.utils.ShiroUtils;
import com.internetCafes.spms.common.utils.entity.page.PageItemDTO;
import com.internetCafes.spms.common.utils.entity.page.PageItemUtil;
import com.internetCafes.spms.common.utils.entity.page.PageItemVO;
import com.internetCafes.spms.core.exception.RRException;
import com.internetCafes.spms.core.exception.RRExceptionCodeEnum;
import com.internetCafes.spms.web.customer.bizservice.area.IEntAreaBizService;
import com.internetCafes.spms.web.customer.common.cont.AreaConst;
import com.internetCafes.spms.web.customer.common.cont.CommonConst;
import com.internetCafes.spms.web.customer.common.util.UserInfoUtil;
import com.internetCafes.spms.web.customer.entity.area.Area;
import com.internetCafes.spms.web.customer.entity.area.AreaManager;
import com.internetCafes.spms.web.customer.entity.area.AreaSale;
import com.internetCafes.spms.web.customer.entity.customer.Customer;
import com.internetCafes.spms.web.customer.entity.user.EntUserInfo;
import com.internetCafes.spms.web.customer.model.area.*;
import com.internetCafes.spms.web.customer.model.user.EntUserAreaPagingReq;
import com.internetCafes.spms.web.customer.model.user.EntUserAreaPagingRes;
import com.internetCafes.spms.web.customer.model.user.EntUserInfoPo;
import com.internetCafes.spms.web.customer.model.user.UserInfoDo;
import com.internetCafes.spms.web.customer.service.area.IAreaManagerService;
import com.internetCafes.spms.web.customer.service.area.IAreaSaleService;
import com.internetCafes.spms.web.customer.service.area.IAreaService;
import com.internetCafes.spms.web.customer.service.customer.ICustomerService;
import com.internetCafes.spms.web.customer.service.user.IEntUserInfoService;
import com.internetCafes.spms.web.sys.model.UserInfo;
import com.internetCafes.spms.web.tenant.common.TenantConst;
import com.internetCafes.spms.web.tenant.model.TenantDeptInfoPlus;
import com.internetCafes.spms.web.tenant.model.podo.TenantDeptInfoPlusDo;
import com.internetCafes.spms.web.tenant.service.ITenantDeptInfoPlusService;
import com.sms.common.util.hutool.core.bean.BeanUtil;
import com.sms.common.util.hutool.core.collection.CollectionUtil;
import com.sms.common.util.hutool.core.date.DateTime;
import com.sms.common.util.hutool.core.util.ObjectUtil;
import com.sms.common.util.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企业区域管理业务层层
 */
@Service
public class EntAreaBizServiceImpl implements IEntAreaBizService {

    @Autowired
    private IAreaService areaService;
    @Autowired
    private IAreaManagerService areaManagerService;
    @Autowired
    private IAreaSaleService areaSaleService;
    @Autowired
    private IEntUserInfoService userInfoService;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private ITenantDeptInfoPlusService deptInfoPlusService;

    @Override
    public EntAreaDetailForSaleRes detailEntAreaSaleDetailByAreaId(Long id) {

        EntAreaDetailPo areaDetailPo = areaService.getAreaDetailForSaleByAreaId(id);
        if (ObjectUtil.isNull(areaDetailPo)) {
            throw new RRException(RRExceptionCodeEnum.DATA_NOT_EXIST);
        }
        UserInfo userEntity = ShiroUtils.getUserEntity();
        EntAreaSaleDo entAreaSaleDo = new EntAreaSaleDo();
        entAreaSaleDo.setAreaId(id);
        List<EntAreaSalePo> salePoList = areaSaleService.listPo(entAreaSaleDo);
        Date nowDate = new Date();
        EntAreaDetailForSaleRes result = entAreaDetailForSale(areaDetailPo, nowDate, userEntity);
        if (CollectionUtil.isNotEmpty(salePoList)) {
            List<EntAreaDetailForSaleRes.SaleInfo> saleInfoList
                    = salePoList.stream().map(areaSalePo ->
                            result.new SaleInfo(areaSalePo.getSaleId(), areaSalePo.getSaleName(),
                                    areaSalePo.getColorCode(), areaSalePo.getAlwaysFlag(),
                                    areaSalePo.getEndTime()))
                    .collect(Collectors.toList());
            result.setAreaSaleList(saleInfoList);
        }
        return result;
    }

    @Override
    public boolean deleteEntAreaUserConfig(EntAreaUserConfigReq req) {
        if (AreaConst.AreaUserConfigTypeEnum.MANAGER.getId().equals(req.getTypeId())) {
            return areaManagerService.deleteManagerConfig(req);
        } else if (AreaConst.AreaUserConfigTypeEnum.SALE.getId().equals(req.getTypeId())) {
            return areaSaleService.deleteConfig(req);
        } else {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }
    }

    @Override
    public List<EntAreaDetailForSaleRes> listAreaDetailForSale(EntAreaDetailReq req) {
        EntAreaDetailDo entAreaDetailDo = new EntAreaDetailDo();
        BeanUtil.copyProperties(req, entAreaDetailDo);
        UserInfo userEntity = ShiroUtils.getUserEntity();
        // 修改 2022-0907 如果不是管理员，但是是管理层 还需要显示他部门以下的人区域信息
        if (!UserInfoUtil.entSuperAdminJudge(userEntity)) {
            entAreaDetailDo.setUserId(userEntity.getId());
            if (UserInfoUtil.managerJudge(userEntity)) {
                List<Area> areaAllListPo = areaService.list();
                /*
                 * 如果是根据用户分配进行筛选
                 */
                List<Long> deptAreaIdList = areaListFilterByUser(areaAllListPo)
                        .stream().map(Area::getId).collect(Collectors.toList());
                entAreaDetailDo.setDeptAreaIdList(deptAreaIdList);
            }
        }

        // 获取区域列表准备
        List<EntAreaDetailPo> areaForSaleList = areaService.listAreaDetailForSale(entAreaDetailDo);
        List<EntAreaDetailPo> areaList = areaForSaleList.stream().filter(po -> AreaConst.AreaTypeEnum.AREA.getId().equals(po.getTypeId())).collect(Collectors.toList());
        List<Long> areaIdList = areaList.stream().map(EntAreaDetailPo::getId).collect(Collectors.toList());

        Map<Long, List<EntAreaSalePo>> saleListGroupByAreaId = new HashMap<>();
        if (CollectionUtil.isNotEmpty(areaIdList)) {
            saleListGroupByAreaId = areaSaleService.listPo(new EntAreaSaleDo().setAreaIdList(areaIdList))
                    .stream()
                    .collect(Collectors.groupingBy(EntAreaSalePo::getAreaId));
        }

        Map<Long, List<EntAreaDetailPo>> detailGroupByParentId = areaList.stream()
                .collect(Collectors.groupingBy(EntAreaDetailPo::getParentId));
        Date nowDate = new Date();

        Map<Long, List<EntAreaSalePo>> finalSaleListGroupByAreaId = saleListGroupByAreaId;
        return areaForSaleList.stream()
                .filter(po -> AreaConst.AreaTypeEnum.CITY.getId().equals(po.getTypeId()))
                .map(po -> {
                    EntAreaDetailForSaleRes res = entAreaDetailForSale(po, nowDate, userEntity);
                    if (detailGroupByParentId.containsKey(po.getId())) {
                        res.setChildren(
                                detailGroupByParentId.get(po.getId())
                                        .stream()
                                        .map(childPo -> {
                                            EntAreaDetailForSaleRes child = entAreaDetailForSale(childPo, nowDate, userEntity);
                                            if (CommonConst.FlagEnum.IS.getId().equals(res.getDistributionAble())) {
                                                child.setDistributionAble(CommonConst.FlagEnum.IS.getId());
                                            }
                                            if (finalSaleListGroupByAreaId.containsKey(childPo.getId())) {
                                                List<EntAreaSalePo> areaSalePoList = finalSaleListGroupByAreaId.get(childPo.getId());
                                                child.setAreaSaleList(
                                                        areaSalePoList.stream().map(areaSalePo ->
                                                                        child.new SaleInfo(areaSalePo.getSaleId(), areaSalePo.getSaleName(),
                                                                                areaSalePo.getColorCode(), areaSalePo.getAlwaysFlag(),
                                                                                areaSalePo.getEndTime()))
                                                                .collect(Collectors.toList()));
                                                child.setAreaSaleNames(areaSalePoList.stream().map(EntAreaSalePo::getSaleName).collect(Collectors.joining("、")));
                                            }
                                            return child;
                                        })
                                        .collect(Collectors.toList()));
                    }
                    return res;
                }).collect(Collectors.toList());
    }

    /**
     * 封装区域销售信息
     *
     * @param po         区域西南西
     * @param nowDate    当前时间
     * @param userEntity 当前用户
     * @return 区域名单节点数据
     */
    private EntAreaDetailForSaleRes entAreaDetailForSale(EntAreaDetailPo po, Date nowDate, UserInfo userEntity) {
        EntAreaDetailForSaleRes res = new EntAreaDetailForSaleRes();
        BeanUtil.copyProperties(po, res);
        if (CommonConst.FlagEnum.IS.getId().equals(po.getManagerAlwaysFlag())) {
            res.setEffectiveDays(AreaConst.EFFECTIVE_ALWAYS);
        } else {
            if (ObjectUtil.isNotNull(po.getManagerEndTime())) {
                long cityManagerEffectiveDays = Duration.between(nowDate.toInstant(), po.getManagerEndTime().toInstant()).toDays();
                res.setEffectiveDays(++cityManagerEffectiveDays + AreaConst.MANAGE_TIME_UNIT);
            }
        }
        res.setDistributionAble(
                (UserInfoUtil.entSuperAdminJudge(userEntity) || ShiroUtils.getUserId().equals(po.getManagerId())) ?
                        CommonConst.FlagEnum.IS.getId() : CommonConst.FlagEnum.NOT.getId());
        return res;
    }

    @Override
    public List<EntAreaDetailRes> listEntAreaDetailRList(EntAreaDetailReq req) {
        EntAreaDetailDo entAreaDetailDo = new EntAreaDetailDo();
        BeanUtil.copyProperties(req, entAreaDetailDo);
        UserInfo userEntity = ShiroUtils.getUserEntity();
        // 修改 2022-0907 如果不是管理员，但是是管理层 还需要显示他部门以下的人区域信息
        if (!UserInfoUtil.entSuperAdminJudge(userEntity)) {
            entAreaDetailDo.setUserId(userEntity.getId());
            if (UserInfoUtil.managerJudge(userEntity)) {
                List<Area> areaAllListPo = areaService.list();
                /*
                 * 如果是根据用户分配进行筛选
                 */
                List<Long> deptAreaIdList = areaListFilterByUser(areaAllListPo)
                       .stream().map(Area::getId).collect(Collectors.toList());
                entAreaDetailDo.setDeptAreaIdList(deptAreaIdList);
            }
        }
        List<EntAreaDetailPo> detailList = areaService.listAreaDetailForManager(entAreaDetailDo);
        Map<Long, List<EntAreaDetailPo>> detailGroupByParentId = detailList.stream()
                .filter(po -> AreaConst.AreaTypeEnum.AREA.getId().equals(po.getTypeId()))
                .collect(Collectors.groupingBy(EntAreaDetailPo::getParentId));
        return detailList.stream()
                .filter(po -> AreaConst.AreaTypeEnum.CITY.getId().equals(po.getTypeId()))
                .map(po -> {
                    EntAreaDetailRes res = new EntAreaDetailRes();
                    BeanUtil.copyProperties(po, res);
                    if (detailGroupByParentId.containsKey(po.getId())) {
                        List<EntAreaDetailRes> children = new ArrayList<>();
                        int dealCustomerAmount = 0;
                        int unDealCustomerAmount = 0;
                        for (EntAreaDetailPo child : detailGroupByParentId
                                .get(po.getId())) {
                            EntAreaDetailRes childRes = new EntAreaDetailRes();
                            BeanUtil.copyProperties(child, childRes);
                            children.add(childRes);
                            dealCustomerAmount += child.getDealCustomerAmount();
                            unDealCustomerAmount += child.getUnDealCustomerAmount();
                        }
                        res.setChildren(children);
                        res.setDealCustomerAmount(dealCustomerAmount);
                        res.setUnDealCustomerAmount(unDealCustomerAmount);
                    }
                    return res;
                }).collect(Collectors.toList());
    }

    @Override
    public List<EntAreaExcel> areaExcel(EntAreaExcelReq req) {
        EntAreaUserPagingReq entAreaUserPagingReq = new EntAreaUserPagingReq();
        BeanUtil.copyProperties(req, entAreaUserPagingReq);
        List<EntAreaUserPagingPo> listPo = areaService.entAreaUserPoList(entAreaUserPagingReq);

        return listPo.stream()
                .map(po -> {
                    EntAreaExcel res = new EntAreaExcel();
                    BeanUtil.copyProperties(po, res);
                    return res;
                }).collect(Collectors.toList());
    }

    @Override
    public List<EntUserAreaExcel> entUserAreaExcelList(EntUserAreaPagingReq req) {
        QueryWrapper<EntUserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("tui.dept_id", ShiroUtils.getUserEntity().getDeptId());
        if (ObjectUtil.isNotNull(req)) {
            if (ObjectUtil.isNotNull(req.getSaleId())) {
                queryWrapper.eq("tui.id", req.getSaleId());
            }
        }

        List<EntUserInfoPo> poList = userInfoService.poList(queryWrapper);

        List<Long> saleIdList = poList.stream()
                .map(EntUserInfoPo::getId)
                .collect(Collectors.toList());

        // 获取对应地区详情列表进行数据封装
        List<EntSaleAreaListPo> entSaleAreaList
                = areaService.saleAreaListPo(new EntSaleAreaListDo().setSaleIdList(saleIdList));

        Map<Long, Map<Long, List<EntSaleAreaListPo>>> areaListGroupBySaleIdAndCityId = entSaleAreaList.stream()
                .collect(Collectors.groupingBy(EntSaleAreaListPo::getSaleId
                        , Collectors.groupingBy(EntSaleAreaListPo::getCityId)));
        DateTime now = DateTime.now();
        return poList.stream().map(po -> {
                    EntUserAreaPagingRes areaPagingRes = userAreaPagingResInfoEncap(now, po, areaListGroupBySaleIdAndCityId);
                    return userAreaExcelEncap(areaPagingRes);
                })
                .sorted(
                        Comparator.comparing(EntUserAreaExcel::getArea, (x, y) -> {
                            if (StrUtil.isNotBlank(x)) {
                                if (StrUtil.isNotBlank(y)) {
                                    return x.length() > y.length() ? 1 : -1;
                                }
                                return 1;
                            }
                            if (StrUtil.isNotBlank(y)) {
                                return -1;
                            }
                            return 0;
                        }).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 封装用户区域信息
     *
     * @param areaPagingRes 请求信息
     * @return 客户导出信息
     */
    private EntUserAreaExcel userAreaExcelEncap(EntUserAreaPagingRes areaPagingRes) {
        EntUserAreaExcel entUserAreaExcel = new EntUserAreaExcel();
        // 姓名
        entUserAreaExcel.setName(areaPagingRes.getNickName());

        String areas = "-";
        // 区域
        if (CollectionUtil.isNotEmpty(areaPagingRes.getSaleList())) {
            areas = areaPagingRes.getSaleList().stream()
                    .map(city -> {
                        String cityName = city.getCityName();
                        if (CollectionUtil.isNotEmpty(city.getAreaList())) {
                            return cityName + "-" + city.getAreaList()
                                    .stream()
                                    .map(area -> area.getAreaName() + area.getDayAmount() + AreaConst.MANAGE_TIME_UNIT)
                                    .collect(Collectors.joining("、"));
                        }
                        return null;
                    })
                    .filter(ObjectUtil::isNotNull)
                    .collect(Collectors.joining(";"));
        }
        entUserAreaExcel.setArea(areas);
        return entUserAreaExcel;
    }

    @Override
    public List<EntAreaUserExcel> entAreaUserExcelList(EntAreaUserPagingReq req) {
        List<EntAreaUserPagingPo> listPo = areaService.entAreaUserPoList(req);
        Date nowDate = new Date();

        return listPo.stream()
                .map(po -> {
                    EntAreaUserExcel res = new EntAreaUserExcel();
                    BeanUtil.copyProperties(po, res);
                    if (CommonConst.FlagEnum.IS.getId().equals(po.getCityManagerAlwaysFlag())) {
                        res.setCityManagerEffectiveDays(AreaConst.EFFECTIVE_ALWAYS);
                    } else {
                        if (ObjectUtil.isNotNull(po.getCityManagerEndTime())) {
                            long cityManagerEffectiveDays = Duration.between(nowDate.toInstant(), po.getCityManagerEndTime().toInstant()).toDays();
                            res.setCityManagerEffectiveDays(++cityManagerEffectiveDays + AreaConst.MANAGE_TIME_UNIT);
                        }
                    }

                    if (CommonConst.FlagEnum.IS.getId().equals(po.getManagerAlwaysFlag())) {
                        res.setManagerEffectiveDays(AreaConst.EFFECTIVE_ALWAYS);
                    } else {
                        if (ObjectUtil.isNotNull(po.getManagerEndTime())) {
                            long managerEffectiveDays = Duration.between(nowDate.toInstant(), po.getManagerEndTime().toInstant()).toDays();
                            res.setManagerEffectiveDays(++managerEffectiveDays + AreaConst.MANAGE_TIME_UNIT);
                        }
                    }
                    return res;
                }).collect(Collectors.toList());
    }

    @Override
    public PageItemVO<EntUserAreaPagingRes> userAreaPaging(PageItemDTO<EntUserAreaPagingReq> req) {
        Page<EntUserInfo> pageDo = new Page<>(req.getPageNum(), req.getPageSize());
        EntUserAreaPagingReq conditions = req.getConditions();
        UserInfoDo userInfoDo = new UserInfoDo();
        BeanUtil.copyProperties(conditions, userInfoDo);
        userInfoDo.setManagerFlag(CommonConst.FlagEnum.NOT.getId());
        if (!UserInfoUtil.entSuperAdminJudge(ShiroUtils.getUserEntity())) {
            userInfoDo.setManagerId(ShiroUtils.getUserId());
        }
        userInfoDo.setTenantId(ShiroUtils.getUserTenantId());
        Page<EntUserInfoPo> pagingPo = userInfoService.poPaging(pageDo, userInfoDo);
        PageItemVO<EntUserAreaPagingRes> pagingRes = PageItemUtil.toPageItemVO(pagingPo, new PageItemVO<>());

        List<Long> saleIdList = pagingPo.getRecords().stream()
                .map(EntUserInfoPo::getId)
                .collect(Collectors.toList());

        // 获取对应地区详情列表进行数据封装
        List<EntSaleAreaListPo> entSaleAreaList = areaService.saleAreaListPo(new EntSaleAreaListDo().setSaleIdList(saleIdList));

        Map<Long, Map<Long, List<EntSaleAreaListPo>>> areaListGroupBySaleIdAndCityId = entSaleAreaList.stream()
                .collect(Collectors.groupingBy(EntSaleAreaListPo::getSaleId
                        , Collectors.groupingBy(EntSaleAreaListPo::getCityId)));

        DateTime now = DateTime.now();

        pagingRes.setRecords(
                pagingPo.getRecords()
                        .stream()
                        .map(po -> userAreaPagingResInfoEncap(now, po, areaListGroupBySaleIdAndCityId))
                        .collect(Collectors.toList()));

        return pagingRes;
    }

    /**
     * 封装销售负责的区域信息，并计算还有多少时间到期
     *
     * @param now                            当前时间
     * @param po                             po数据库实体类
     * @param areaListGroupBySaleIdAndCityId 区域列表分组信息
     * @return 但前用户的区域分配信息
     */
    private EntUserAreaPagingRes userAreaPagingResInfoEncap(DateTime now, EntUserInfoPo po, Map<Long, Map<Long, List<EntSaleAreaListPo>>> areaListGroupBySaleIdAndCityId) {
        EntUserAreaPagingRes res = new EntUserAreaPagingRes();
        res.setId(po.getId()).setName(po.getName()).setNickName(po.getNickName());

        // 找到这个人对应的管理区域
        if (areaListGroupBySaleIdAndCityId.containsKey(po.getId())) {
            res.setSaleList(new ArrayList<>());
            Map<Long, List<EntSaleAreaListPo>> areaListGroupByCityId = areaListGroupBySaleIdAndCityId.get(po.getId());
            for (Map.Entry<Long, List<EntSaleAreaListPo>> entry : areaListGroupByCityId.entrySet()) {
                EntUserAreaPagingRes.SaleArea areaEntry = res.new SaleArea();
                areaEntry.setCityName(CollectionUtil.getFirst(entry.getValue()).getCityName());
                areaEntry.setAreaList(
                        entry.getValue().stream()
                                .map(value -> {
                                    EntUserAreaPagingRes.SaleArea.AreaInfo areaInfo = areaEntry.new AreaInfo();
                                    areaInfo.setId(value.getAreaId());
                                    areaInfo.setAreaName(value.getAreaName());
                                    if (CommonConst.FlagEnum.IS.getId().equals(value.getAlwaysFlag())) {
                                        areaInfo.setDayAmount(AreaConst.EFFECTIVE_ALWAYS);
                                    } else {
                                        if (ObjectUtil.isNotNull(value.getEndTime())) {
                                            long amount = Duration.between(now.toInstant(), value.getEndTime().toInstant()).toDays();
                                            areaInfo.setDayAmount(++amount + AreaConst.MANAGE_TIME_UNIT);
                                        }
                                    }
                                    return areaInfo;
                                }).collect(Collectors.toList()));
                res.getSaleList().add(areaEntry);
            }
        }
        return res;
    }

    @Override
    public EntAreaUserDetailRes entAreaUserDetail(Long id) {
        EntAreaUserDetailPo detailPo = areaService.entAreaUserPoDetail(id);
        // 获取销售信息
        List<EntUserInfo> saleList = userInfoService.saleListByAreaId(id);
        EntAreaUserDetailRes res = new EntAreaUserDetailRes();
        BeanUtil.copyProperties(detailPo, res);
        res.setSaleList(saleList.stream().map(EntUserInfo::getName).collect(Collectors.toList()));
        res.setSaleIdList(saleList.stream().map(EntUserInfo::getId).collect(Collectors.toList()));
        return res;
    }

    @Override
    public PageItemVO<EntAreaUserPagingRes> entAreaUserPoPaging(PageItemDTO<EntAreaUserPagingReq> req) {
        Page<Area> pageDo = new Page<>(req.getPageNum(), req.getPageSize());
        EntAreaUserPagingReq conditions = req.getConditions();
        if (!UserInfoUtil.entSuperAdminJudge(ShiroUtils.getUserEntity())) {
            conditions.setUserId(ShiroUtils.getUserEntity().getUserId());
        }
        Page<EntAreaUserPagingPo> pagingPo = areaService.entAreaUserPoPaging(pageDo, conditions);
        PageItemVO<EntAreaUserPagingRes> pagingRes = PageItemUtil.toPageItemVO(pagingPo, new PageItemVO<>());
        Date nowDate = new Date();
        pagingRes.setRecords(
                pagingPo.getRecords()
                        .stream()
                        .map(po -> {
                            EntAreaUserPagingRes res = new EntAreaUserPagingRes();
                            BeanUtil.copyProperties(po, res);
                            if (CommonConst.FlagEnum.IS.getId().equals(po.getCityManagerAlwaysFlag())) {
                                res.setCityManagerEffectiveDays(AreaConst.EFFECTIVE_ALWAYS);
                            } else {
                                if (ObjectUtil.isNotNull(po.getCityManagerEndTime())) {
                                    long cityManagerEffectiveDays = Duration.between(nowDate.toInstant(), po.getCityManagerEndTime().toInstant()).toDays();
                                    res.setCityManagerEffectiveDays(++cityManagerEffectiveDays + AreaConst.MANAGE_TIME_UNIT);
                                }
                            }

                            if (CommonConst.FlagEnum.IS.getId().equals(po.getManagerAlwaysFlag())) {
                                res.setManagerEffectiveDays(AreaConst.EFFECTIVE_ALWAYS);
                            } else {
                                if (ObjectUtil.isNotNull(po.getManagerEndTime())) {
                                    long managerEffectiveDays = Duration.between(nowDate.toInstant(), po.getManagerEndTime().toInstant()).toDays();
                                    res.setManagerEffectiveDays(++managerEffectiveDays + AreaConst.MANAGE_TIME_UNIT);
                                }
                            }
                            res.setDistributionAble(
                                            ShiroUtils.getUserId().equals(po.getManagerId()) ?
                                                    CommonConst.FlagEnum.IS.getId() : CommonConst.FlagEnum.NOT.getId())
                                    .setEndTime(po.getManagerEndTime());
                            return res;
                        }).collect(Collectors.toList())
        );
        return pagingRes;
    }

    @Override
    public boolean entAreaUserConfig(EntAreaUserConfigReq req) {

        if (AreaConst.AreaUserConfigTypeEnum.MANAGER.getId().equals(req.getTypeId())) {
            return areaManagerService.config(req);
        }
        if (AreaConst.AreaUserConfigTypeEnum.SALE.getId().equals(req.getTypeId())) {
            return areaSaleService.config(req);
        }
        if (AreaConst.AreaUserConfigTypeEnum.TOGETHER.getId().equals(req.getTypeId())) {
            return configAreaSaleAndManager(req);
        }
        throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
    }

    /**
     * 同事配置区域管理人和销售
     *
     * @param req 请求参数
     * @return true/false
     */
    private boolean configAreaSaleAndManager(EntAreaUserConfigReq req) {
        // 参数判断
        if (ObjectUtil.isNull(req.getCityId()) || ObjectUtil.isNull(req.getAreaId())) {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }
        if (ObjectUtil.isNotNull(req.getManagerId())) {
            // 管理人数据创建
            EntAreaUserConfigReq managerConfigReq = new EntAreaUserConfigReq();
            BeanUtil.copyProperties(req, managerConfigReq);
            managerConfigReq.setAreaIdList(Collections.singletonList(req.getAreaId()));
            managerConfigReq.setUserIdList(Collections.singletonList(req.getManagerId()));
            managerConfigReq.setEndTime(req.getManagerEndTime());
            managerConfigReq.setAlwaysFlag(req.getManagerAlwaysFlag());
            boolean managerConfigResult = areaManagerService.config(managerConfigReq);
            if (!managerConfigResult) {
                return false;
            }
        } else {
            EntAreaUserConfigReq managerDeleteConfigReq = new EntAreaUserConfigReq();
            managerDeleteConfigReq.setCityId(req.getCityId());
            managerDeleteConfigReq.setAreaIdList(Collections.singletonList(req.getAreaId()));
            areaManagerService.deleteManagerConfig(managerDeleteConfigReq);
        }
        if (CollectionUtil.isNotEmpty(req.getSaleIdList())) {
            // 销售数据创建
            EntAreaUserConfigReq saleConfigReq = new EntAreaUserConfigReq();
            BeanUtil.copyProperties(req, saleConfigReq);
            saleConfigReq.setUserIdList(req.getSaleIdList());
            saleConfigReq.setEndTime(req.getSaleEndTime());
            saleConfigReq.setAlwaysFlag(req.getSaleAlwaysFlag());
            boolean saleConfigResult = areaSaleService.config(saleConfigReq);
            if (!saleConfigResult) {
                throw new RRException(RRExceptionCodeEnum.CUSTOMER_CONFIG_SALE_ERROR);
            }
        } else {
            EntAreaUserConfigReq saleDeleteConfigReq = new EntAreaUserConfigReq();
            saleDeleteConfigReq.setCityId(req.getCityId());
            saleDeleteConfigReq.setAreaIdList(Collections.singletonList(req.getAreaId()));
            areaSaleService.deleteConfig(saleDeleteConfigReq);
        }
        return true;
    }

    @Override
    public List<EntAreaTreeRes> entAreaTree(EntAreaTreeReq req) {
        List<Area> areaAllListPo = areaService.list();

        /*
         * 如果是根据用户分配进行筛选
         */
        if (AreaConst.AreaTreeAction.USER_DISTRIBUTE.getId().equals(req.getActionId())) {
            areaAllListPo = areaListFilterByUser(areaAllListPo);
        }

        // 获取市列表
        List<EntAreaTreeRes> resList = areaAllListPo.stream()
                .filter(po -> AreaConst.AreaTypeEnum.CITY.getId().equals(po.getTypeId()))
                .map(po -> new EntAreaTreeRes().setId(po.getId()).setTypeId(po.getTypeId()).setName(po.getName()))
                .collect(Collectors.toList());

        // 便利市下区域
        for (EntAreaTreeRes res : resList) {
            res.setChildren(
                    areaAllListPo.stream()
                            .filter(po -> res.getId().equals(po.getParentId()))
                            .map(po ->
                                    new EntAreaTreeRes().setId(po.getId()).setTypeId(po.getTypeId()).setName(po.getName()))
                            .collect(Collectors.toList()));
        }

        return resList;
    }

    /**
     * 根据当前用户类型，对区域列表进行过滤操作
     * <p>
     * 超级管理员：看到所有区域
     * 部门管理员：看到所在部门的人员的管理/负责区域
     * 其他：看到自己被分配的区域
     * 修改 注释 by zj 2022-03-25
     * </p>
     *
     * @param areaAllListPo 区域列表
     * @return 有权查看的区域的列表
     */
    private List<Area> areaListFilterByUser(List<Area> areaAllListPo) {
        UserInfo userEntity = ShiroUtils.getUserEntity();
        if (UserInfoUtil.entSuperAdminJudge(userEntity)) {
            return areaAllListPo;
        }
        // 如果是管理层，看到所在部门的人员的管理/负责区域
        List<Long> areaIdList = new ArrayList<>();
        List<Long> cityIdList = new ArrayList<>();
        if (UserInfoUtil.managerJudge(userEntity)) {
            List<Long> deptIdList = new ArrayList<>();
            deptIdList.add(-1L);
            // 如果部门id为 0，获取全部部门id 并且添加部门id 0
            if (TenantConst.TENANT_DEPT_ROOT_PARENT_ID.equals(userEntity.getTenantDeptId())) {
                List<Long> allDeptIdList = deptInfoPlusService.list()
                        .stream().map(TenantDeptInfoPlus::getId).collect(Collectors.toList());
                deptIdList.addAll(allDeptIdList);
                deptIdList.add(TenantConst.TENANT_DEPT_ROOT_PARENT_ID);
            } else {
                // 如果不为 0 获取该部门已经部门以下部门
                TenantDeptInfoPlusDo deptInfoPlusDo = new TenantDeptInfoPlusDo();
                deptInfoPlusDo.setTenantId(userEntity.getTenantId());
                deptInfoPlusDo.setAncestorId(userEntity.getTenantDeptId());
                List<Long> innerDeptIdList = deptInfoPlusService.deptList(deptInfoPlusDo)
                        .stream().map(TenantDeptInfoPlus::getId).collect(Collectors.toList());
                deptIdList.addAll(innerDeptIdList);
            }
            // 获取 部门下的人的管理区域 / 部门下的人的销售区域
            EntAreaDo areaDo = new EntAreaDo();
            areaDo.setManagerDeptIdList(deptIdList);
            // 管理人管理区域
            List<EntAreaPo> areaList = new ArrayList<>();
            List<EntAreaPo> managerAreaList = areaService.listPo(areaDo);
            if (CollectionUtil.isNotEmpty(managerAreaList)) {
                areaList.addAll(managerAreaList);
            }

            areaDo = new EntAreaDo().setSaleDeptIdList(deptIdList);
            // 销售负责区域
            List<EntAreaPo> saleAreaPoList = areaService.listPo(areaDo);
            if (CollectionUtil.isNotEmpty(saleAreaPoList)) {
                areaList.addAll(saleAreaPoList);
            }

            areaList.forEach(areaPo -> {
                if (ObjectUtil.isNotNull(areaPo.getId())) {
                    areaIdList.add(areaPo.getId());
                }
                if (ObjectUtil.isNotNull(areaPo.getParentId())) {
                    cityIdList.add(areaPo.getParentId());
                }
            });
        }

        if (CommonConst.FlagEnum.IS.getId().equals(userEntity.getAreaManagerFlag())) {
            // 获取管理层配置的数据
            List<AreaManager> managerList = areaManagerService.list(new LambdaQueryWrapper<AreaManager>()
                    .eq(AreaManager::getManagerId, ShiroUtils.getUserId())
                    .eq(AreaManager::getEffectiveFlag, CommonConst.FlagEnum.IS.getId()));
            if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(managerList)) {
                for (AreaManager managerArea : managerList) {
                    if (ObjectUtil.isNotNull(managerArea.getAreaId())) {
                        areaIdList.add(managerArea.getAreaId());
                    }
                    if (ObjectUtil.isNotNull(managerArea.getCityId())) {
                        cityIdList.add(managerArea.getCityId());
                    }
                }
            }
        } else {
            List<AreaSale> saleList = areaSaleService.list(
                    new LambdaQueryWrapper<AreaSale>()
                            .eq(AreaSale::getSaleId, ShiroUtils.getUserId())
                            .eq(AreaSale::getEffectiveFlag, CommonConst.FlagEnum.IS.getId()));
            if (cn.hutool.core.collection.CollectionUtil.isNotEmpty(saleList)) {
                for (AreaSale saleArea : saleList) {
                    if (ObjectUtil.isNotNull(saleArea.getAreaId())) {
                        areaIdList.add(saleArea.getAreaId());
                    }
                    if (ObjectUtil.isNotNull(saleArea.getCityId())) {
                        cityIdList.add(saleArea.getCityId());
                    }
                }
            }
        }
        cn.hutool.core.collection.CollectionUtil.distinct(areaIdList);
        cn.hutool.core.collection.CollectionUtil.distinct(cityIdList);
        return areaAllListPo.stream()
                .filter(po -> areaIdList.contains(po.getId()) || cityIdList.contains(po.getId())
                        || (cityIdList.contains(po.getParentId()) && TenantConst.TENANT_DEPT_ROOT_PARENT_ID.equals(userEntity.getTenantDeptId())))
                .collect(Collectors.toList());
    }

    @Override
    public List<EntAreaListRes> entAreaList(EntAreaListReq req) {
        EntAreaDo entAreaDo = new EntAreaDo();
        BeanUtil.copyProperties(req, entAreaDo);
        UserInfo userEntity = ShiroUtils.getUserEntity();
        if (AreaConst.AreaListAction.DISTRIBUTE.getId().equals(req.getActionId())
                && !UserInfoUtil.entSuperAdminJudge(userEntity)) {
            entAreaDo.setManagerId(userEntity.getId());
        }
        return areaService.poList(entAreaDo)
                .stream()
                .map(po ->
                        new EntAreaListRes().setId(po.getId()).setName(po.getName())
                                .setManagerId(po.getManagerId()).setManagerName(po.getManagerName())
                )
                .collect(Collectors.toList());
    }

    @Override
    public PageItemVO<EntAreaPagingRes> entAreaPaging(PageItemDTO<EntAreaPagingReq> req) {
        Page<Area> pageDo = new Page<>(req.getPageNum(), req.getPageSize());

        EntAreaPagingReq conditions = req.getConditions();
        QueryWrapper<Area> queryWrapper = new QueryWrapper<>();

        if (ObjectUtil.isNotNull(conditions)) {
            if (ObjectUtil.isNotNull(conditions.getDistributionFlag()) && CommonConst.FlagEnum.IS.getId().equals(conditions.getDistributionFlag())) {
                queryWrapper.isNull("xam.id").isNull("xam2.id");
            }
            if (ObjectUtil.isNotNull(conditions.getAreaId())) {
                queryWrapper.and(qw ->
                        qw.eq("`xa`.id", conditions.getAreaId())
                                .or()
                                .eq("`xa`.parent_id", conditions.getAreaId()));
            }
            if (ObjectUtil.isNotNull(conditions.getManagerId())) {
                queryWrapper.and(qw ->
                        qw.eq("xam.manager_id", conditions.getManagerId())
                                .or()
                                .eq("xam2.manager_id", conditions.getManagerId()));
            }
            UserInfo userEntity = ShiroUtils.getUserEntity();
            //  2021/12/10 周五 只能看到他自己负责的区域，管理员账号能看到所有
            if (!UserInfoUtil.entSuperAdminJudge(userEntity)) {
                queryWrapper.and(qw ->
                        qw.eq("xam.manager_id", userEntity.getId())
                                .or()
                                .eq("xam2.manager_id", userEntity.getId()));
            }
        }
        PageItemUtil.order(req, queryWrapper);
        queryWrapper.orderByDesc("xa.parent_id", "xa.id");

        Page<EntAreaPagingPo> pagingPo = areaService.entAreaPoPaging(pageDo, queryWrapper);
        PageItemVO<EntAreaPagingRes> pagingRes = PageItemUtil.toPageItemVO(pagingPo, new PageItemVO<>());
        pagingRes.setRecords(
                pagingPo.getRecords()
                        .stream()
                        .map(po -> {
                            EntAreaPagingRes res = new EntAreaPagingRes();
                            BeanUtil.copyProperties(po, res);
                            return res;
                        }).collect(Collectors.toList()));

        return pagingRes;
    }

    @Override
    public boolean areaUpdate(EntAreaUpdateReq req) {
        Area areaUpdateDo = new Area();
        BeanUtil.copyProperties(req, areaUpdateDo);
        return areaService.updateById(areaUpdateDo);
    }

    @Override
    public boolean areaDelete(List<Long> areaIdList) {
        // 查看区域下子区域 并判断子区域是否一起删除
        List<Long> areaChildrenIdList = areaService.list(new LambdaQueryWrapper<Area>().in(Area::getParentId, areaIdList))
                .stream()
                .map(Area::getId)
                .filter(areaId -> !areaIdList.contains(areaId))
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(areaChildrenIdList)) {
            throw new RRException(RRExceptionCodeEnum.AREA_HAS_CHILDREN);
        }

        // 区域下客户
        List<Customer> customerListPo = customerService.list(new LambdaQueryWrapper<Customer>()
                .and(lqw -> lqw.in(Customer::getCityId, areaIdList)
                        .or()
                        .in(Customer::getAreaId, areaIdList)));

        if (CollectionUtil.isNotEmpty(customerListPo)) {
            throw new RRException(RRExceptionCodeEnum.AREA_HAS_CUSTOMER);
        }
        return areaService.removeByIds(areaIdList);
    }

    @Override
    public boolean areaSave(EntAreaSaveReq req) {

        // 参数验证
        if (!AreaConst.AreaTypeEnum.getAreaTypeIdList().contains(req.getTypeId()) || StrUtil.isBlank(req.getName())) {
            throw new RRException(RRExceptionCodeEnum.PARAM_ERROR);
        }

        // 区域名称验证
        List<Area> areaList =
                areaService.list(new LambdaQueryWrapper<Area>().eq(Area::getName, req.getName()));
        if (CollectionUtil.isNotEmpty(areaList)) {
            throw new RRException(RRExceptionCodeEnum.PARAM_REPEAT);
        }

        // 保存信息
        Area areaSaveDo = new Area();
        BeanUtil.copyProperties(req, areaSaveDo);
        return areaService.save(areaSaveDo);
    }
}
